package us.icitap.commandcenter.business.ejb.persistence;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import us.icitap.commandcenter.utils.Utils;

@Entity
@Table(name="CALL",schema="MPC")
@SequenceGenerator(name="CALL_SEQ",initialValue=1, allocationSize=1)
//@TableGenerator(name="CALL_IDS",table="AUTO_IDS",valueColumnName="LAST_ID",initialValue=1, allocationSize=1)
public class Call implements Serializable {

	@Id
	@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CALL_SEQ")
//	@GeneratedValue(strategy=GenerationType.TABLE, generator="CALL_IDS")
	@Column(nullable = false)
	private Integer id;
	
	@Size(max=50, message="Ne kutine e telefonuesit nuk mund te shkruani me shume se 50 karaktere")
	@Column(length=50)
	private String caller;
	
	@Column(name="ANONYMOUS_CALLER")
	private boolean anonymousCaller;
	@NotNull(message="Duhet te plotesoni arsyen e telefonates")
	@ManyToOne
	@JoinColumn(name="CALL_REASON_ID")
	private CallReason callReason;
	
	@Size(max=500, message="Ne kutine e pershkrimit nuk mund te shkruani me shume se 500 karaktere")
	@Column(length=500)
	private String description;
	
	@Size(max=200, message="Ne kutine e adreses nuk mund te shkruani me shume se 200 karaktere")
	@Column(length=200)
	private String address;
	
	
	@Column(name="RECORD_USER", length=60)
	private String recordUser;
	
	@Temporal(TemporalType.TIMESTAMP)
	@Column(name="CALL_DATE")
	private Date callDate;
	
	@NotNull(message="Duhet te plotesoni zonen e mbulimit")
	@ManyToOne
	@JoinColumn(name="MAIN_DISPATCHER_ID")
	private Dispatcher mainDispatcher;
	
	@ManyToOne
	@JoinColumn(name="PREVIOUS_DISPATCHER_ID")
	private Dispatcher previousDispatcher;
	
	@ManyToOne
	@JoinColumn(name="COMMAND_CENTER_ID")
	private CommandCenter commandCenter;
	

	@NotNull(message="Duhet te plotesoni klasifikimin e telefonates")
	@ManyToOne
	@JoinColumn(name="ACTUAL_GRADE_ID")
	private Grade actualGrade;
	
	@Enumerated(EnumType.STRING)
	@Column(name="ACTUAL_STATUS")
	private CallStatusEnum actualStatus;
	
	@Temporal(TemporalType.TIMESTAMP)
	@Column(name="RECORD_DATE")
	private Date recordDate;
	
	@ManyToOne
	@JoinColumn(name="UNIQUE_NUMBER_ID")
	private UniqueNumber uniqueNumber;
	
	@ManyToOne(cascade=CascadeType.ALL)
	@JoinColumn(name="BASE_CALL_ID")
	private Call baseCall;
	
	@OneToMany(mappedBy="baseCall",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
	private List<Call> relatedCallList;
	
	
	@Temporal(TemporalType.TIMESTAMP)
	@Column(name="STARTED_VERIF_DATE")
	private Date startedVerificationDate;
	
	@Column(name="STARTED_VERIF_USER", length=60)
	private String startedVerificationUser;
	
	@Column(name="FALSE_CALL")
	private boolean falseCall = false;
	
	
	
	
	@Size(max=2000, message="Ne kutine e shenimeve mbi verifikimin nuk mund te shkruani me shume se 2000 karaktere")
	@Column(name="VERIFICATION_NOTES", length=2000)
	private String verificationNotes;
	
	@NotNull(message="Arsyeja e telefonates pas verifikimit nuk mund te jete bosh")
	@JoinColumn(name="VERIFIED_REASON_ID")
	private CallReason verifiedCallReason;
	
	@ManyToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
	@JoinTable(name="MPC.CALL_POLICE_ACTION", joinColumns=@JoinColumn(name="CALL_ID"), inverseJoinColumns=@JoinColumn(name="POLICE_ACTION_ID"))
	private Set<PoliceAction> policeActionList;
	
	@Temporal(TemporalType.TIMESTAMP)
	@Column(name="VERIFICATION_DATE")
	private Date verificationDate;
	
	@Column(name="VERIFICATION_USER", length=60)
	private String verificationUser;
	
	@Column(name="FOR_SUPERVISOR")
	private boolean forSupervisor= false;
	
	@OneToMany(mappedBy="call")
	private List<CallManagement> callManagementList;
	
	@Column(name="OFFICER_CALL")
	private	boolean officerCall;
	
	@Transient
	private boolean infoDisplayed = false;
	
	
	@Transient
	private String userByStatus;
	
	@Transient
	public String getUserByStatus(){
		if(CallStatusEnum.N.equals(this.actualStatus)) userByStatus =  this.getRecordUser();
		else if(CallStatusEnum.WV.equals(this.actualStatus)) userByStatus =  this.getStartedVerificationUser();
		else if(CallStatusEnum.V.equals(this.actualStatus)) userByStatus =  this.getVerificationUser();
		else userByStatus = null;
		return userByStatus;
	}
	
	
	
	
	@Transient
	public String getNotificationsInfo(){
		String cmStr = "";
		for (CallManagement cm : this.getCallManagementList()) {
			if(cm.getWhoIsNotified()== null) continue;
			cmStr += ", " + cm.getWhoIsNotified() + " ne oren " + Utils.formatedTime(cm.getRecordDate());
		}
		
		cmStr = cmStr.replaceFirst(", ", "");
		
		return cmStr;
	}
	
	@Transient
	public String getPatrolsInfo(){
		String cmStr = "";
		for (CallManagement cm : this.getCallManagementList()) {
			if(cm.getPatrols()== null) continue;
			cmStr += ", " + cm.getPatrols() + " ne oren " + Utils.formatedTime(cm.getRecordDate());
		}
		
		cmStr = cmStr.replaceFirst(", ", "");
		
		return cmStr;
	}
	
	@Transient
	public String getGivenOrdersInfo(){
		String cmStr = "";
		for (CallManagement cm : this.getCallManagementList()) {
			if(cm.getGivenOrders()== null) continue;
			cmStr += ", " + cm.getGivenOrders() + " ne oren " + Utils.formatedTime(cm.getRecordDate());
		}
		
		cmStr = cmStr.replaceFirst(", ", "");
		
		return cmStr;
	}
	
	@Transient
	public String getNotesInfo(){
		String cmStr = "";
		for (CallManagement cm : this.getCallManagementList()) {
			if(cm.getNotes()== null) continue;
			cmStr += ", " + "Ora: "  +  Utils.formatedTime(cm.getRecordDate())  + cm.getNotes() + "\n";
		}
		
		cmStr = cmStr.replaceFirst(", ", "");
		
		return cmStr;
	}
	
	@Transient
	public String getNotesInfoForHtml(){
		String cmStr = "";
		for (CallManagement cm : this.getCallManagementList()) {
			if(cm.getNotes()== null) continue;
			cmStr += ",<br/>" + "Ora: "  +  Utils.formatedTime(cm.getRecordDate()) + " -> " + cm.getNotes() ;
		}
		
		cmStr = cmStr.replaceFirst(",<br/>", "");
		
		return cmStr;
	}
	
	@Transient
	public String getVerifNotesFormatted(){
		if(this.getVerificationNotes() != null)
			return this.getVerificationNotes().replace("<br/>", ", ");
		else
			return "";
		
	}
	
	@Transient
	public String getPoliceActionListString(){
		String s = "";
		if(this.policeActionList != null)
		for (PoliceAction pa : this.policeActionList) {
			s += ", " + pa.getTag();
		}
		return s.replaceFirst(",", "");
	
	}
	

	

	
	public Call() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Call(String recordUser) {
		super();
		this.recordUser = recordUser;
	}

	
	/*@Transient
	public Grade getActualGrade(){
		for (CallGradeHistory gradeHistory : this.gradeHistoryList) {
			if(gradeHistory.isActive()) return gradeHistory.getGrade();
		}
		return null;
	}
	
	public void setActualGrade(Grade grade){
		
		if(gradeHistoryList != null && !gradeHistoryList.isEmpty())
			for (CallGradeHistory gradeHistory : this.gradeHistoryList) {
				gradeHistory.setActive(false);
			}
		else if(gradeHistoryList == null) gradeHistoryList = new ArrayList<CallGradeHistory>();
		
		CallGradeHistory callGradeHistory = new CallGradeHistory();
		callGradeHistory.setGrade(grade);
		callGradeHistory.setCall(this);
		callGradeHistory.setActive(true);
		callGradeHistory.setGradeDate(new Date());
		
		this.gradeHistoryList.add(callGradeHistory);
		
	}
	

	public CallStatusEnum getActualStatus(){
		
		return this.actualStatus;
	}
	
	
	
	public void setActualStatus(CallStatusEnum callStatus){
		this.actualStatus =callStatus;
		if(statusHistoryList == null) statusHistoryList = new ArrayList<CallStatusHistory>();
		
		CallStatusHistory callStatusHistory = new CallStatusHistory();
		callStatusHistory.setStatus(this.actualStatus);
		callStatusHistory.setCall(this);
		callStatusHistory.setStatusDate(new Date());
		
		this.statusHistoryList.add(callStatusHistory);
	}
	
	*/
	
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getCaller() {
		return caller;
	}

	public void setCaller(String caller) {
		this.caller = caller;
	}

	public boolean isAnonymousCaller() {
		return anonymousCaller;
	}

	public void setAnonymousCaller(boolean anonymousCaller) {
		this.anonymousCaller = anonymousCaller;
	}

	public CallReason getCallReason() {
		return callReason;
	}

	public void setCallReason(CallReason callReason) {
		this.callReason = callReason;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}


	public Dispatcher getMainDispatcher() {
		return mainDispatcher;
	}

	public void setMainDispatcher(Dispatcher mainDispatcher) {
		this.mainDispatcher = mainDispatcher;
	}

	public CommandCenter getCommandCenter() {
		return commandCenter;
	}

	public void setCommandCenter(CommandCenter commandCenter) {
		this.commandCenter = commandCenter;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}



	public Date getCallDate() {
		return callDate;
	}

	public void setCallDate(Date callDate) {
		this.callDate = callDate;
	}

	public Date getRecordDate() {
		return recordDate;
	}

	public void setRecordDate(Date recordDate) {
		this.recordDate = recordDate;
	}

	public UniqueNumber getUniqueNumber() {
		return uniqueNumber;
	}

	public void setUniqueNumber(UniqueNumber uniqueNumber) {
		this.uniqueNumber = uniqueNumber;
	}

	public String getRecordUser() {
		return recordUser;
	}

	public void setRecordUser(String recordUser) {
		this.recordUser = recordUser;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Call other = (Call) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	public String getVerificationNotes() {
		return verificationNotes;
	}

	public void setVerificationNotes(String verificationNotes) {
		this.verificationNotes = verificationNotes;
	}


	public CallReason getVerifiedCallReason() {
		return verifiedCallReason;
	}

	public void setVerifiedCallReason(CallReason verifiedCallReason) {
		this.verifiedCallReason = verifiedCallReason;
	}

	public Set<PoliceAction> getPoliceActionList() {
		return policeActionList;
	}

	public void setPoliceActionList(Set<PoliceAction> policeActionList) {
		
		this.policeActionList = policeActionList;
		
	}

	public Date getVerificationDate() {
		return verificationDate;
	}

	public void setVerificationDate(Date verificationDate) {
		this.verificationDate = verificationDate;
	}

	public Grade getActualGrade() {
		return actualGrade;
	}

	public void setActualGrade(Grade actualGrade) {
		this.actualGrade = actualGrade;
	}

	public CallStatusEnum getActualStatus() {
		return actualStatus;
	}

	public void setActualStatus(CallStatusEnum actualStatus) {
		this.actualStatus = actualStatus;
	}

	public Call getBaseCall() {
		return baseCall;
	}

	public void setBaseCall(Call baseCall) {
		this.baseCall = baseCall;
	}
	
	public String getToolTip(){
		
		String newCallData =  
		"<tr>" +
		"<td >Telefonuesi:</td>" +
		"<td class='boldLabels'>"+(this.isAnonymousCaller()?"ANONIM":this.getCaller())+"</td>" +
		"</tr>" +
		(this.isOfficerCall()?("<tr>" +
				"<td ></td>" +
				"<td class='boldLabels'>Telefonuesi eshte Punonjes Policie</td>" +
				"</tr>"):"") + 
		
		
		"<tr>" +
		"<td>Koha e tel.:</td>" +
		"<td class='boldLabels'>"+Utils.formatedDateTime(this.getRecordDate())+"</td>" +
		"</tr>" +
		
		"<tr>" +
		"<td>Adresa:</td>" +
		"<td class='boldLabels'>"+this.getAddress()+"</td>" +
		"</tr>" +
		
		"<tr>" +
		"<td>Pershkrimi:</td>" +
		"<td class='boldLabels'>"+this.getDescription()+"</td>" +
		"</tr>" +

		"<tr>" +
		"<td>Problemi:</td>" +
		"<td class='boldLabels'>"+((this.getCallReason()!=null)?this.getCallReason().getTag():"") +"</td>" +
		"</tr>" +
		
		"<tr>" +
		"<td>Zona e mbulimit:</td>" +
		"<td class='boldLabels'>"+((this.getMainDispatcher()!=null)?this.getMainDispatcher().getName():"") +"</td>" +
		"</tr>" 

		;
		
		
		if(CallStatusEnum.N.equals(this.getActualStatus())){
			return " <h2>Telefonata eshte e re, akoma nuk eshte deleguar</h2>" +
					"<table> " + newCallData + "</table>";
		}
		else if(CallStatusEnum.WV.equals(this.getActualStatus())){
			return "<h2>Telefonata eshte deleguar per tu verifikuar</h2>" +
					" <table> " + 
					newCallData + 
					
					"<tr>" +
					"<td>Kush eshte njoftuar:</td>" +
					"<td class='boldLabels'>"+this.getNotificationsInfo()+"</td>" +
					"</tr>" +
					"<tr>" +
					"<td>Patrullat e derguara:</td>" +
					"<td class='boldLabels'>"+this.getPatrolsInfo()+"</td>" +
					"</tr>" +
					"<tr>" +
					"<td>Shenime mbi delegimin:</td>" +
					"<td class='boldLabels'>"+this.getNotesInfoForHtml()+"</td>" +
					"</tr>" +
					
					"</table>";
		}
		else if(CallStatusEnum.V.equals(this.getActualStatus())){
			return "<h2>Telefonata eshte verifikuar</h2> <table> " + 
					newCallData + 
					
					"<tr>" +
					"<td>Kush eshte njoftuar:</td>" +
					"<td class='boldLabels'>"+this.getNotificationsInfo()+"</td>" +
					"</tr>" +
					"<tr>" +
					"<td>Patrullat e derguara:</td>" +
					"<td class='boldLabels'>"+this.getPatrolsInfo()+"</td>" +
					"</tr>" +
					"<tr>" +
					"<td>Shenime mbi delegimin:</td>" +
					"<td class='boldLabels'>"+this.getNotesInfoForHtml()+"</td>" +
					"</tr>" +
					
					"<tr>" +
					"<td>Shenime mbi verifikimin:</td>" +
					"<td class='boldLabels'>"+this.getVerificationNotes()+"</td>" +
					"</tr>" +
					"<tr>" +
					"<td>Problemi pas verifikimit:</td>" +
					"<td class='boldLabels'>"+((this.getVerifiedCallReason()!=null)?this.getVerifiedCallReason().getTag():"")+"</td>" +
					"</tr>" +
					"<tr>" +
					"<td>Lista e masave te marra:</td>" +
					"<td class='boldLabels'>"+this.getPoliceActionListString()+"</td>" +
					"</tr>" +
					"<tr>" +
					
					"</table>";
		}
		else return null;
	}

	public List<Call> getRelatedCallList() {
		return relatedCallList;
	}

	public void setRelatedCallList(List<Call> relatedCallList) {
		this.relatedCallList = relatedCallList;
	}


	

	public boolean isForSupervisor() {
		return forSupervisor;
	}

	public void setForSupervisor(boolean forSupervisor) {
		this.forSupervisor = forSupervisor;
	}

	public List<CallManagement> getCallManagementList() {
		return callManagementList;
	}

	public void setCallManagementList(List<CallManagement> callManagementList) {
		this.callManagementList = callManagementList;
	}

	public String getVerificationUser() {
		return verificationUser;
	}

	public void setVerificationUser(String verificationUser) {
		this.verificationUser = verificationUser;
	}

	public Dispatcher getPreviousDispatcher() {
		return previousDispatcher;
	}

	public void setPreviousDispatcher(Dispatcher previousDispatcher) {
		this.previousDispatcher = previousDispatcher;
	}

	public boolean isOfficerCall() {
		return officerCall;
	}

	public void setOfficerCall(boolean officerCall) {
		this.officerCall = officerCall;
	}

	public boolean isInfoDisplayed() {
		return infoDisplayed;
	}

	public void setInfoDisplayed(boolean infoDisplayed) {
		this.infoDisplayed = infoDisplayed;
	}

	public Date getStartedVerificationDate() {
		return startedVerificationDate;
	}

	public void setStartedVerificationDate(Date startedVerificationDate) {
		this.startedVerificationDate = startedVerificationDate;
	}

	public String getStartedVerificationUser() {
		return startedVerificationUser;
	}

	public void setStartedVerificationUser(String startedVerificationUser) {
		this.startedVerificationUser = startedVerificationUser;
	}




	public boolean isFalseCall() {
		return falseCall;
	}




	public void setFalseCall(boolean falseCall) {
		this.falseCall = falseCall;
	}


	
	
	
}
